#include <regx52.h>
#include <intrins.h>

// 定义XPT2046触摸屏模块的引脚
sbit XPT2046_DIN = P3^4;   // 数据输入引脚
sbit XPT2046_CS = P3^5;    // 片选引脚
sbit XPT2046_DCLK = P3^6;  // 时钟引脚
sbit XPT2046_DOUT = P3^7;  // 数据输出引脚

/**
 * @brief 延时1ms函数
 * @details 利用空操作和循环在11.0592MHz晶振下实现约1ms的延时
 */
void XPT_Delay_1ms() //@11.0592MHz
{
    unsigned char i, j;

    _nop_();  // 空操作指令，提供精确延时
    _nop_();
    _nop_();
    i = 11;   // 外层循环计数器
    j = 190;  // 内层循环计数器
    do
    {
        while (--j); // 内层循环，用于延时
    } while (--i); // 外层循环
}

/**
 * @brief 从XPT2046模块读取AD值
 * 
 * @param Command 指令字节，指定读取通道和其他配置
 *                高4位：指令通道选择；低4位：命令设置
 * @return unsigned int 读取的AD值
 *         若是12位分辨率（高精度模式），返回值为右移4位后的结果；
 *         若是8位分辨率（低精度模式），返回值为右移8位后的结果。
 */
unsigned int XPT2046_Read(unsigned char Command)
{
    unsigned int ADC_Value = 0;  // 存储读取的AD值
    unsigned char i = 0;         // 循环变量

    XPT2046_CS = 0;    // 选中XPT2046模块
    XPT2046_DCLK = 0;  // 初始化时钟引脚为低电平

    // 发送8位指令给XPT2046
    for (i = 0; i < 8; i++)
    {
        XPT2046_DIN = Command & (0x80 >> i);  // 根据指令位设置数据引脚
        XPT2046_DCLK = 1;                     // 拉高时钟引脚，触发数据采样
        XPT2046_DCLK = 0;                     // 时钟引脚恢复低电平
    }

    // 接收16位AD转换数据
    for (i = 0; i < 16; i++)
    {
        XPT2046_DCLK = 1;  // 拉高时钟引脚，触发数据输出
        XPT2046_DCLK = 0;  // 恢复低电平
        if (XPT2046_DOUT)  // 如果数据引脚为高电平
        {
            ADC_Value |= (0x8000 >> i);  // 将对应位设置为1
        }
        XPT_Delay_1ms();  // 每次采样后延时1ms
    }

    XPT2046_CS = 1;  // 释放XPT2046模块

    // 根据分辨率要求返回结果
    if (Command & 0x08)  // 低精度模式（8位）
    {
        return ADC_Value >> 8;  // 返回右移8位的结果
    }
    else  // 高精度模式（12位）
    {
        return ADC_Value >> 4;  // 返回右移4位的结果
    }
}
